package edu.android.com;

import java.util.ArrayList;
import java.util.Iterator;

import android.app.Activity;
import android.graphics.Color;
import android.graphics.Rect;
import android.os.Bundle;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;

public class framework extends Activity{
	public ArrayList <node> mNodes = new ArrayList();
	public int mmNrNodes = 0;
	public int mmStartNode = 0;
	public int DELAY = 500;
	public int mMaxNrNodes = 15;
	
	public int[] cost;
	public int[] order;
	public boolean[] used;
	
	public boolean mTBState = false;
	FrameLayout ll;
	
	//Display informations
	private	Rect rectgle = new Rect();
	private	Window window;
	private	Display display;
	public TextView mDisplayContent;
	
	@Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        
        //Load the layout
        setContentView(R.layout.framework);
        ll = (FrameLayout)findViewById(R.id.fwNodes);
        
        mDisplayContent = (TextView)findViewById(R.id.displayContent);
        
        //Pick number of nodes
        final EditText mNrNodes = (EditText)findViewById(R.id.nrNodes);
        Button mPickNrNodes = (Button)findViewById(R.id.pickNrNodes);
        
        mPickNrNodes.setOnClickListener(new View.OnClickListener() {
			@Override
			public void onClick(View v) {
				// TODO Auto-generated method stub
				delOldNodes(mmNrNodes);
				
				String str = mNrNodes.getText().toString();
				try {
				    mmNrNodes = Integer.parseInt(str);
				} catch(NumberFormatException nfe) {
				   mmNrNodes = 0;
				   mNrNodes.setText("");
				} 
				
				//Add nodes
				if(0 < mmNrNodes && mmNrNodes <= mMaxNrNodes)
					addNodes(mmNrNodes);
				else
					mNrNodes.setText("");
			}
		});
        
        //See if we add edges or no
        ToggleButton mTB = (ToggleButton)findViewById(R.id.toggleButton);
        
        mTB.setOnCheckedChangeListener(new OnCheckedChangeListener()
        {

			@Override
			public void onCheckedChanged(CompoundButton arg0, boolean arg1) {
				// TODO Auto-generated method stub
				mTBState = arg1;
				if(mTBState == false){
					if(firstNode != null && firstNode.getUsed() == false && edge.mWithCost == false)
						firstNode.initialize();
					flag = false;
				}
			}
        	
        });
        
	}//OnCreate end
	
	//Touch Events
	boolean flag = false;
	node firstNode,secondNode;
	float OffsetX,OffsetY;
	node touched;
	
	@Override
	public boolean onTouchEvent(MotionEvent ev){
		int action = ev.getAction();

		//"removing the status bar"
		float touchX = ev.getX();
		float touchY = ev.getY();
		
		window = getWindow();
        window.getDecorView().getWindowVisibleDisplayFrame(rectgle);
        touchY =touchY - ll.getTop() - rectgle.top;
    
        //Managing the MotionEvent whith edges
		switch(action){
		case MotionEvent.ACTION_DOWN: //select a node
			touched = touchdNode(touchX,touchY);
			
			if(touched != null){
				touched.bringToFront();
				
				OffsetX = touchX - touched.getX();
				OffsetY = touchY - touched.getY();
			}
			
			if(touched != null && mTBState == true){//if ON and node selected
				if(flag == false){
					firstNode = touched;
					firstNode.setColor(Color.GRAY);
					firstNode.invalidate();
					flag = true;
				}
				else{
					secondNode = touched;
					flag = false;
					firstNode.initialize();
					secondNode.initialize();
					addEdgeBetween(firstNode,secondNode);
				}
			}
			else{//If ON and no node selected
				if(mTBState == true){
					flag = false;
					firstNode.initialize();
				}
			}
			break;
		case MotionEvent.ACTION_MOVE://move a node
			if(touched != null){
				touched.setXY(touchX - OffsetX, touchY - OffsetY);
				touched.invalidate();
			}
			break;
		case MotionEvent.ACTION_UP://release a node
			touched = null;
			break;
		case MotionEvent.ACTION_CANCEL:
			touched = null;
			break;
		}
		
		return true;
	}
	
	private node touchdNode(float touchX,float touchY){
		node touched = null;
		for(int i = 0;i < mmNrNodes;i ++){
			node cur = mNodes.get(i);
			if(intersects(touchX,touchY,cur.getX(),cur.getY(),cur.getRay()) == true)
					touched = cur;
		}
		return touched;
	}
	private boolean intersects(float xT,float yT,float xN,float yN,float ray)
	{
		return (double)(xT - xN) * (xT - xN) +  (yT - yN) * (yT - yN) <= (double)ray * ray;
	}
	
	//Add edges
	private boolean btPressed = true;
	private boolean flagCost = true;
	private Button  bt;
	private EditText et;
	private edge mEdge;
	private int mId = 0;
	
	private void addEdgeBetween(node a,node b){
		if(a == b)
			return ;
		if(a.edgeExist(b)){
			if(edge.mOrientated == false){
				a.removeEdge(b);
				ll.removeView(b.removeEdge(a));
			}
			else{
				ll.removeView(a.removeEdge(b));
			}
			return ;
		}
		mEdge = new edge(this);
		mEdge.setId(++mId);
		mEdge.createEdge(a, b);
		ll.addView(mEdge);
		
		//with cost
		if(edge.mWithCost || edge.mWithFlow){
			EditText eb = (EditText)findViewById(R.id.costEB);
			if(edge.mWithCost)
				eb.setHint("Cost:");
			else
				eb.setHint("Capacity:");
			
			if(btPressed == true)
				switchCost();
			btPressed = false;
			
			bt = (Button)findViewById(R.id.pickCost);
			et = (EditText)findViewById(R.id.costEB);
			bt.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					String text = et.getText().toString();
					int mCost = 0;
					et.setText("");
							
					try{
					mCost = Integer.parseInt(text);
					}catch(NumberFormatException nfe) {
						  mCost = 0;
					}
					if(edge.mWithCost)
						mEdge.setCost(mCost);
					else
						mEdge.setCapacity(mCost);
					
					switchCost();
					btPressed = true;
				}
			});
		}
		//Bring to front
		a.bringToFront();	b.bringToFront();
	}
	private void switchCost(){
		LinearLayout ll1 = (LinearLayout)findViewById(R.id.fwWidgets);
		LinearLayout ll2 = (LinearLayout)findViewById(R.id.fwCost);
		
		if(flagCost == true){
			ll1.setVisibility(LinearLayout.INVISIBLE);
			ll2.setVisibility(FrameLayout.VISIBLE);
		}
		else{
			ll1.setVisibility(LinearLayout.VISIBLE);
			ll2.setVisibility(FrameLayout.INVISIBLE);
		}
		flagCost = !flagCost;
	}
	
	//Manage the arrayList of nodes
	private void addNodes(int mNr)
	{
		window= getWindow();
        window.getDecorView().getWindowVisibleDisplayFrame(rectgle);
        display = getWindowManager().getDefaultDisplay();
        
		for(int i = 0;i < mNr;i ++)
		{
			node nd = new node(this);
			nd.setNodeNumber(i+1);
			boolean colisionDetected;
			//Check for colisions
			do{
				float _X = nd.getRay() + (float)Math.random()*(display.getWidth() - nd.getRay() * 2);
				float _Y = nd.getRay() + (float)Math.random()*(display.getHeight()-nd.getRay() * 2 - ll.getTop() - rectgle.top);
				nd.setXY(_X,_Y);
				
				colisionDetected = false;
				for(int j = 0;j < i;j ++)
					if(colision(nd,mNodes.get(j)) == true){
						colisionDetected = true;
						break;
					}
				//colisionDetected = false;
			}while(colisionDetected == true);
			
			nd.invalidate();
			mNodes.add(nd);
			ll.addView(nd);
		}
	}
	private boolean colision(node a,node b){
		return Math.sqrt((double)(a.getX() - b.getX()) * (a.getX() - b.getX()) + (a.getY() - b.getY()) * (a.getY() - b.getY())) < (double)a.getRay() + (double)b.getRay();
	}
	
	private void delOldNodes(int mNr){
		mDisplayContent.setText("");
		
		if(mNodes.isEmpty() == true)
			return ;
		for(int i = 0;i < mNr;i ++){
			mNodes.get(i).removeEdges(ll);
			ll.removeView(mNodes.get(i));
		}
		
    	mNodes.clear();
	}
}
